package auction

import auth.User

class Auction {
	
	/*
	 Die Attribute werden definiert.
	 */
	String heading
	Date startDate
	Date endDate
	String description
	BigDecimal startprice
	int auctionDuration
	String filename
	boolean notificationSent = false
	
	
	/*
	Die Relationen zu Bid und User werden definiert.
	Eine Auktion hat viele Gebote.		(1:n)
	Eine Auktion gehört zu einem User 	(1:1) 
	 */
	static hasMany = [bids:Bid]
	static belongsTo = [user:User]
	
	/*@see: http://www.grails.org/doc/latest/ref/Domain%20Classes/transients.html
	 * Dieses Tag bewirkt, dass die genannten Attribute nicht hart in die Datenbank geschrieben werden.
	 */
	static transients = ['highestBid', 'minBidAmount', 'hasEnded']
	
	/*
	Hier werden die Beschränkungen der Domain-Attribute definiert.
	 */
    static constraints = {
		heading(blank:false)
		startDate()
		endDate(blank:false, validator:futureDate)
		//TODO: add minimum date
		//bloody grails docu is a liar. Using min:new Date() doesn't work.
		description()
		startprice(blank:false,
			min:1.0, 
			scale:2,)
		filename(blank:true, nullable:true)
		notificationSent(nullable: false)
    }
	

	/* ---------- SETTINGS ---------- */
	static biddingStep = 0.50 // minimum increase to previous bid
	static int minDuration = 1 // minimum duration for an auction in days
	
	/* ---------- VALIDATORS --------*/
	/**
	* Date must be in the future
	*/
   static futureDate = {val,obj ->
	   return new Date() < val
   }
	
   /* ----------- EVENT LISTENERS --------- */
   
   /**
    * wenn sich das Datum der Auktion verändert, sollte der EmailJob neu gesetzt werden
    */
   def afterUpdate() {
	   System.out.println("Scheduled email submission for " + heading + " at " + endDate);
	   CheckEndDatesJob.schedule(endDate, ['auctionInstance':this])
	  // CheckEndDatesJob.schedule(new Date(), ['auctionInstance':this]) //FOR TESTING PURPOSES ONLY
   }
   
   /**
    * nach dem anlegen der Auktion sollte die EndBenachrichtigung gesetzt werden
    */
   def afterInsert() {
	   System.out.println("Scheduled email submission for " + heading + " at " + endDate);
	   CheckEndDatesJob.schedule(endDate,['auctionInstance':this])
	  //CheckEndDatesJob.schedule(new Date(), ['auctionInstance':this]) //FOR TESTING PURPOSES ONLY
   }
   
	/* ---------- METHODS ---------- */
	/**
	* @return Bid instance with highest amount, null if no bids have been made
	*/
	def getHighestBid(){
		if (this.bids){
			def highest = Bid.findAllByAuction(this, [sort:"bidAmount", order:"desc", max:1])
			return highest[0]
		}
		else{
			return null
		}
	}
	
	def getSecondHighestBid(){
		if (this.bids){
			def secondhighest = Bid.findAllByAuction(this, [sort:"bidAmount", order:"desc", max:2])
			return secondhighest[1]
		}
		else{
			return null
		}
	}
	
	/**
	* adds something to the highest bid or returns the entry bid if no bids exist
	* @return BigDecimal minimum amount for the next bid
	*/
	def getMinBidAmount(){		
		if (getHighestBid()){
			def highest = this.getHighestBid()
			return highest.bidAmount + biddingStep
		}
		else{
			return startprice
		}
		
	}
	
	/**
	 * @return boolean - true if auction was started 7 days ago
	 */
	def getHasEnded(){
		return this.endDate < new Date()
	}
	
	/**
	* @return String mit dem Wert 'heading' des Objekts
	*/
	String toString(){
		heading
	}
	
	
}
